package la.iok.hzsvn.lewin.movie.shopmovie.service;

import la.iok.hzsvn.lewin.movie.core.exception.ErrorCode;
import la.iok.hzsvn.lewin.movie.core.movieservice.vo.MovieLevelVo;
import la.iok.hzsvn.lewin.movie.services.MovieServiceInvoker;
import la.iok.hzsvn.lewin.movie.shopmovie.entity.Carpool;
import la.iok.hzsvn.lewin.movie.shopmovie.entity.Player;
import la.iok.hzsvn.lewin.movie.shopmovie.entity.PlayerFee;
import la.iok.hzsvn.lewin.movie.shopmovie.entity.ShopMovie;
import la.iok.hzsvn.lewin.movie.shopmovie.mapper.PlayerFeeMapper;
import la.iok.hzsvn.lewin.mybatis.service.BaseServiceImpl;
import la.iok.hzsvn.share.annotations.NotNull;
import la.iok.hzsvn.share.annotations.Nullable;
import la.iok.hzsvn.share.collection.IdOperators;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

@Service
public class PlayerFeeServiceImpl extends BaseServiceImpl<PlayerFee, PlayerFeeMapper, Long> implements PlayerFeeService {
    private final ShopMovieService shopMovieService;
    private final PlayerService playerService;
    private final MovieServiceInvoker movieServiceInvoker;
    public PlayerFeeServiceImpl(PlayerFeeMapper mapper,
                                ShopMovieService shopMovieService,
                                PlayerService playerService,
                                MovieServiceInvoker movieServiceInvoker) {
        super(mapper);
        this.shopMovieService = shopMovieService;
        this.playerService = playerService;
        this.movieServiceInvoker = movieServiceInvoker;
    }

    private Long save(@NotNull Player player, @Nullable String name, @Nullable Integer amount, Integer feeType) {
        name = ErrorCode.PROPERTY_CHECK_ERROR.assertNotBlank(name,"名称","名称不能为空");
        ErrorCode.PROPERTY_CHECK_ERROR.assertNotNull(amount,"金额","必须指定金额");
        ErrorCode.PROPERTY_CHECK_ERROR.assertTrue(amount >=0,"金额","金额不能为负数");
        if(feeType == 2){
            ErrorCode.PROPERTY_CHECK_ERROR.assertNotEquals("剧本费",name,"名称","不能额外添加剧本费");
        }
        PlayerFee entity = mapper.selectByWhere("playerId=" + player.getId() + " and feeName='" + name + "'");
        if(entity == null){
            entity = new PlayerFee();
            entity.setFeeName(name);
            entity.setFeeAmount(amount);
            entity.setPlayerId(player.getId());
            entity.setFeeType(feeType);
            if(player.virtualType()){ // 虚拟玩家,已经支付
                entity.setStatus(PlayerFee.STATUS_PAID);
            }
            insertSelective(entity);
        }else{
            if(!Objects.equals(entity.getFeeAmount(), amount)){
                entity.setFeeAmount(amount);
                ErrorCode.RECORD_MODIFIED_ERROR.assertEqual(1,mapper.updateAmount(entity));
            }
        }
        return entity.getId();
    }

    @Override
    public Long saveMovieFee(Player player, Integer amount) {
        return save(player, "剧本费",amount, 1);
    }

    @Nullable
    @Override
    public PlayerFee movieFee(@Nullable Long playerId) {
        if(playerId == null){
            return null;
        }
        return mapper.selectMovieFee(playerId);
    }

    @Override
    public Long saveAdditionalFee(Player player, String name, Integer amount) {
        return save(player, name, amount, 2);
    }

    @Override
    public void updateMovieFee(Carpool carpool) {
        ShopMovie shopMovie = shopMovieService.select(carpool.getShopMovieId());
        if(shopMovie != null){
            List<Player> players = playerService.players(carpool.getId());
            List<MovieLevelVo> levelVo = movieServiceInvoker.movieLevels();
            MovieLevelVo level = IdOperators.find(levelVo, shopMovie.getMovieLevelId());
            ErrorCode.PROPERTY_CHECK_ERROR.assertNotNull(level,()->new Object[]{"剧本类别",String.format("剧本类别(%s)的定义未找到",shopMovie.getMovieLevelId())});
            Integer price = level.getTodayPrice() == null?0:level.getTodayPrice();

            players.forEach(player -> saveMovieFee(player, price));
        }
    }

    @Override
    public int confirmPaid(@NotNull PlayerFee playerFee) {
        return mapper.confirmPaid(playerFee);
    }

    @Override
    public int cancelPayment(PlayerFee playerFee) {
        return mapper.cancelPayment(playerFee);
    }

    @Override
    public int addCouponDeductionAmount(@NotNull Long id, @NotNull Long version, int amount) {
        return mapper.addCouponDeductionAmount(id, amount, version);
    }

    @Override
    public int setCouponDeductionAmount(@NotNull Long id, @NotNull Long version, int amount) {
        return mapper.setCouponDeductionAmount(id, amount, version);
    }
}
